package bytes_coder

import (
	"bytes"
	"encoding/binary"
	jsoniter "github.com/json-iterator/go"
	"reflect"
	"unsafe"
)

var jsonIterator = jsoniter.ConfigCompatibleWithStandardLibrary

func EncodeJsonBytes(value interface{}) ([]byte, error) {
	data, err := jsonIterator.Marshal(value)
	if err != nil {
		return nil, err
	}
	return data, err
}

func DecodeJsonBytes(data []byte, output interface{}) (interface{}, error) {
	err := jsonIterator.Unmarshal(data, output)
	if err != nil {
		return nil, err
	}
	return output, nil
}

func Encode(obj interface{}) ([]byte, error) {
	buf := new(bytes.Buffer)
	if err := binary.Write(buf, binary.LittleEndian, obj); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func Decode(b []byte, data interface{}) (interface{}, error) {
	buf := bytes.NewBuffer(b)
	if err := binary.Read(buf, binary.LittleEndian, data); err != nil {
		return nil, err
	}
	return data, nil
}

/**
structPointer: &MyStruct{}
len: int(unsafe.Sizeof(MyStruct{}))
cap: int(unsafe.Sizeof(MyStruct{}))
*/
func StructToBytes(structPointer unsafe.Pointer, structSize int) []byte {
	var x reflect.SliceHeader
	x.Len = structSize
	x.Cap = structSize
	x.Data = uintptr(unsafe.Pointer(structPointer))
	return *(*[]byte)(unsafe.Pointer(&x))
}

/**
example: (*MyStruct)(structPointer)
*/
func BytesToStruct(bytes []byte) (structPointer unsafe.Pointer) {
	return unsafe.Pointer(
		(*reflect.SliceHeader)(unsafe.Pointer(&bytes)).Data,
	)
}
